package com.foodorder.service;

import com.foodorder.entity.Order;
import com.foodorder.entity.OrderItem;
import com.foodorder.entity.Product;
import com.foodorder.repository.OrderRepository;
import com.foodorder.repository.ProductRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * 订单服务类 - 增强版本，支持事务管理和库存控制
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class OrderService {
    
    private final OrderRepository orderRepository;
    private final ProductRepository productRepository;
    private final InventoryService inventoryService;
    
    /**
     * 创建订单 - 完整的事务处理
     * 
     * @param order 订单信息
     * @return 创建的订单
     */
    @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
    public Order createOrder(Order order) {
        try {
            // 1. 生成订单号
            order.setOrderNo(generateOrderNumber());
            order.setStatus(Order.OrderStatus.PENDING_PAYMENT);
            order.setCreatedAt(LocalDateTime.now());
            order.setUpdatedAt(LocalDateTime.now());
            
            // 2. 验证和预扣库存
            for (OrderItem item : order.getOrderItems()) {
                if (!reserveProductStock(item)) {
                    throw new RuntimeException("商品库存不足: " + item.getProductName());
                }
            }
            
            // 3. 计算订单金额
            calculateOrderAmount(order);
            
            // 4. 保存订单
            Order savedOrder = orderRepository.save(order);
            
            // 5. 设置订单项的订单ID并保存
            for (OrderItem item : savedOrder.getOrderItems()) {
                item.setOrderId(savedOrder.getId());
            }
            
            log.info("订单创建成功，订单号: {}, 用户ID: {}, 总金额: {}", 
                savedOrder.getOrderNo(), savedOrder.getUserId(), savedOrder.getTotalAmount());
            
            return savedOrder;
            
        } catch (Exception e) {
            log.error("创建订单失败: {}", e.getMessage(), e);
            // 回滚已预扣的库存
            rollbackStockReservation(order.getOrderItems());
            throw new RuntimeException("订单创建失败: " + e.getMessage());
        }
    }
    
    /**
     * 取消订单 - 释放库存
     * 
     * @param orderId 订单ID
     * @param reason 取消原因
     */
    @Transactional(rollbackFor = Exception.class)
    public void cancelOrder(Long orderId, String reason) {
        Order order = orderRepository.findById(orderId)
            .orElseThrow(() -> new RuntimeException("订单不存在"));
        
        if (!canCancelOrder(order)) {
            throw new RuntimeException("订单状态不允许取消");
        }
        
        try {
            // 1. 更新订单状态
            order.setStatus(Order.OrderStatus.CANCELLED);
            order.setCancelledAt(LocalDateTime.now());
            order.setCancelReason(reason);
            order.setUpdatedAt(LocalDateTime.now());
            
            // 2. 释放库存
            for (OrderItem item : order.getOrderItems()) {
                boolean released = inventoryService.releaseStock(item.getProductId(), item.getQuantity());
                if (!released) {
                    log.warn("释放库存失败，商品ID: {}, 数量: {}", item.getProductId(), item.getQuantity());
                }
            }
            
            // 3. 保存订单
            orderRepository.save(order);
            
            log.info("订单取消成功，订单号: {}, 取消原因: {}", order.getOrderNo(), reason);
            
        } catch (Exception e) {
            log.error("取消订单失败，订单ID: {}", orderId, e);
            throw new RuntimeException("取消订单失败: " + e.getMessage());
        }
    }
    
    /**
     * 确认支付 - 更新订单状态
     * 
     * @param orderId 订单ID
     * @param paymentMethod 支付方式
     * @param transactionId 交易ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void confirmPayment(Long orderId, String paymentMethod, String transactionId) {
        Order order = orderRepository.findById(orderId)
            .orElseThrow(() -> new RuntimeException("订单不存在"));
        
        if (order.getStatus() != Order.OrderStatus.PENDING_PAYMENT) {
            throw new RuntimeException("订单状态不正确，无法确认支付");
        }
        
        try {
            // 1. 更新订单状态
            order.setStatus(Order.OrderStatus.PAID);
            order.setPaymentMethod(paymentMethod);
            order.setPaymentTransactionId(transactionId);
            order.setPaidAt(LocalDateTime.now());
            order.setUpdatedAt(LocalDateTime.now());
            
            // 2. 更新商品销量
            for (OrderItem item : order.getOrderItems()) {
                productRepository.updateSales(item.getProductId(), item.getQuantity());
            }
            
            // 3. 保存订单
            orderRepository.save(order);
            
            log.info("订单支付确认成功，订单号: {}, 支付方式: {}", order.getOrderNo(), paymentMethod);
            
        } catch (Exception e) {
            log.error("确认支付失败，订单ID: {}", orderId, e);
            throw new RuntimeException("确认支付失败: " + e.getMessage());
        }
    }
    
    /**
     * 更新订单状态
     * 
     * @param orderId 订单ID
     * @param status 新状态
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateOrderStatus(Long orderId, Order.OrderStatus status) {
        Order order = orderRepository.findById(orderId)
            .orElseThrow(() -> new RuntimeException("订单不存在"));
        
        if (!isValidStatusTransition(order.getStatus(), status)) {
            throw new RuntimeException("无效的状态转换: " + order.getStatus() + " -> " + status);
        }
        
        order.setStatus(status);
        order.setUpdatedAt(LocalDateTime.now());
        
        // 根据状态设置时间
        switch (status) {
            case COMPLETED:
                order.setCompletedAt(LocalDateTime.now());
                break;
            case CANCELLED:
                order.setCancelledAt(LocalDateTime.now());
                break;
        }
        
        orderRepository.save(order);
        log.info("订单状态更新成功，订单号: {}, 新状态: {}", order.getOrderNo(), status);
    }
    
    /**
     * 根据用户ID查找订单
     */
    public Page<Order> findByUserId(Long userId, Pageable pageable) {
        return orderRepository.findByUserIdOrderByCreatedAtDesc(userId, pageable);
    }
    
    /**
     * 根据用户ID和状态查找订单
     */
    public Page<Order> findByUserIdAndStatus(Long userId, Order.OrderStatus status, Pageable pageable) {
        return orderRepository.findByUserIdAndStatusOrderByCreatedAtDesc(userId, status, pageable);
    }
    
    /**
     * 根据店铺ID查找订单
     */
    public Page<Order> findByStoreId(Long storeId, Pageable pageable) {
        return orderRepository.findByStoreIdOrderByCreatedAtDesc(storeId, pageable);
    }
    
    /**
     * 根据店铺ID和状态查找订单
     */
    public Page<Order> findByStoreIdAndStatus(Long storeId, Order.OrderStatus status, Pageable pageable) {
        return orderRepository.findByStoreIdAndStatusOrderByCreatedAtDesc(storeId, status, pageable);
    }
    
    /**
     * 根据订单号查找订单
     */
    public Order findByOrderNo(String orderNo) {
        return orderRepository.findByOrderNo(orderNo).orElse(null);
    }
    
    /**
     * 根据ID查找订单
     */
    public Order findById(Long id) {
        return orderRepository.findById(id).orElse(null);
    }
    
    /**
     * 获取用户订单统计
     */
    public Map<String, Object> getUserOrderStats(Long userId) {
        Map<String, Object> stats = new HashMap<>();
        
        // 统计各状态订单数量
        long pendingPaymentCount = orderRepository.countByUserIdAndStatus(userId, Order.OrderStatus.PENDING_PAYMENT);
        long processingCount = orderRepository.countByUserIdAndStatus(userId, Order.OrderStatus.PROCESSING);
        long deliveringCount = orderRepository.countByUserIdAndStatus(userId, Order.OrderStatus.DELIVERING);
        long completedCount = orderRepository.countByUserIdAndStatus(userId, Order.OrderStatus.COMPLETED);
        long cancelledCount = orderRepository.countByUserIdAndStatus(userId, Order.OrderStatus.CANCELLED);
        
        stats.put("pendingPayment", pendingPaymentCount);
        stats.put("processing", processingCount);
        stats.put("delivering", deliveringCount);
        stats.put("completed", completedCount);
        stats.put("cancelled", cancelledCount);
        
        // 总订单数
        stats.put("totalOrders", orderRepository.countByUserId(userId));
        
        // 总消费金额
        BigDecimal totalAmount = orderRepository.sumTotalAmountByUserIdAndStatus(userId, Order.OrderStatus.COMPLETED);
        stats.put("totalAmount", totalAmount != null ? totalAmount : BigDecimal.ZERO);
        
        return stats;
    }
    
    /**
     * 获取店铺订单统计
     */
    public Map<String, Object> getStoreOrderStats(Long storeId) {
        Map<String, Object> stats = new HashMap<>();
        
        // 统计各状态订单数量
        long pendingPaymentCount = orderRepository.countByStoreIdAndStatus(storeId, Order.OrderStatus.PENDING_PAYMENT);
        long paidCount = orderRepository.countByStoreIdAndStatus(storeId, Order.OrderStatus.PAID);
        long preparingCount = orderRepository.countByStoreIdAndStatus(storeId, Order.OrderStatus.PREPARING);
        long processingCount = orderRepository.countByStoreIdAndStatus(storeId, Order.OrderStatus.PROCESSING);
        long deliveringCount = orderRepository.countByStoreIdAndStatus(storeId, Order.OrderStatus.DELIVERING);
        long completedCount = orderRepository.countByStoreIdAndStatus(storeId, Order.OrderStatus.COMPLETED);
        long cancelledCount = orderRepository.countByStoreIdAndStatus(storeId, Order.OrderStatus.CANCELLED);
        
        stats.put("pendingPayment", pendingPaymentCount);
        stats.put("paid", paidCount);
        stats.put("preparing", preparingCount);
        stats.put("processing", processingCount);
        stats.put("delivering", deliveringCount);
        stats.put("completed", completedCount);
        stats.put("cancelled", cancelledCount);
        
        // 总订单数
        stats.put("totalOrders", orderRepository.countByStoreId(storeId));
        
        // 总销售额
        BigDecimal totalAmount = orderRepository.sumTotalAmountByStoreIdAndStatus(storeId, Order.OrderStatus.COMPLETED);
        stats.put("totalAmount", totalAmount != null ? totalAmount : BigDecimal.ZERO);
        
        // 今日订单数
        LocalDateTime startOfDay = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0);
        LocalDateTime endOfDay = startOfDay.plusDays(1);
        long todayOrders = orderRepository.countByStoreIdAndCreatedAtBetween(storeId, startOfDay, endOfDay);
        stats.put("todayOrders", todayOrders);
        
        // 今日销售额
        BigDecimal todayAmount = orderRepository.sumTotalAmountByStoreIdAndStatusAndCreatedAtBetween(
            storeId, Order.OrderStatus.COMPLETED, startOfDay, endOfDay);
        stats.put("todayAmount", todayAmount != null ? todayAmount : BigDecimal.ZERO);
        
        return stats;
    }
    
    /**
     * 预扣商品库存
     */
    private boolean reserveProductStock(OrderItem item) {
        // 检查商品是否存在且可用
        Product product = productRepository.findById(item.getProductId()).orElse(null);
        if (product == null || product.getStatus() != Product.ProductStatus.AVAILABLE) {
            log.warn("商品不存在或不可用，商品ID: {}", item.getProductId());
            return false;
        }
        
        // 预扣库存
        boolean reserved = inventoryService.reserveStock(item.getProductId(), item.getQuantity());
        if (!reserved) {
            log.warn("库存预扣失败，商品ID: {}, 需要数量: {}", item.getProductId(), item.getQuantity());
            return false;
        }
        
        return true;
    }
    
    /**
     * 回滚库存预扣
     */
    private void rollbackStockReservation(List<OrderItem> orderItems) {
        for (OrderItem item : orderItems) {
            try {
                inventoryService.releaseStock(item.getProductId(), item.getQuantity());
            } catch (Exception e) {
                log.error("回滚库存失败，商品ID: {}", item.getProductId(), e);
            }
        }
    }
    
    /**
     * 计算订单金额
     */
    private void calculateOrderAmount(Order order) {
        // 商品小计
        BigDecimal productAmount = BigDecimal.ZERO;
        for (OrderItem item : order.getOrderItems()) {
            BigDecimal itemTotal = item.getPrice().multiply(BigDecimal.valueOf(item.getQuantity()));
            item.setSubtotal(itemTotal);
            productAmount = productAmount.add(itemTotal);
        }
        
        // 设置商品金额
        order.setProductAmount(productAmount);
        
        // 加上配送费
        BigDecimal totalAmount = productAmount.add(order.getDeliveryFee());
        
        // 减去优惠金额
        if (order.getDiscountAmount() != null) {
            totalAmount = totalAmount.subtract(order.getDiscountAmount());
        }
        
        // 设置总金额
        order.setTotalAmount(totalAmount);
    }
    
    /**
     * 生成订单号
     */
    private String generateOrderNumber() {
        return "ORD" + System.currentTimeMillis() + UUID.randomUUID().toString().substring(0, 4).toUpperCase();
    }
    
    /**
     * 判断订单是否可取消
     */
    private boolean canCancelOrder(Order order) {
        return order.getStatus() == Order.OrderStatus.PENDING_PAYMENT 
            || order.getStatus() == Order.OrderStatus.PAID
            || order.getStatus() == Order.OrderStatus.PROCESSING;
    }
    
    /**
     * 判断状态转换是否有效
     */
    private boolean isValidStatusTransition(Order.OrderStatus currentStatus, Order.OrderStatus newStatus) {
        switch (currentStatus) {
            case PENDING_PAYMENT:
                return newStatus == Order.OrderStatus.PAID 
                    || newStatus == Order.OrderStatus.CANCELLED;
                    
            case PAID:
                return newStatus == Order.OrderStatus.PROCESSING 
                    || newStatus == Order.OrderStatus.CANCELLED;
                    
            case PROCESSING:
                return newStatus == Order.OrderStatus.DELIVERING 
                    || newStatus == Order.OrderStatus.CANCELLED;
                    
            case DELIVERING:
                return newStatus == Order.OrderStatus.COMPLETED 
                    || newStatus == Order.OrderStatus.CANCELLED;
                    
            case COMPLETED:
                return false; // 已完成订单不能改状态
                
            case CANCELLED:
                return false; // 已取消订单不能改状态
                
            default:
                return false;
        }
    }
}